/**
 * Copyright(c) kyle.
 */
package org.example.jvm;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

import static java.lang.invoke.MethodHandles.lookup;

/**
 * MethodHandle基础用法演示
 *
 * @author kyle
 * @version 1.00.00
 * @since [2020-12-03 20:09]
 * @updateUser [Kyle]
 * @updateRemark [说明本次修改内容]
 * @date [2020-12-03 20:09]
 */
public class MethodHandleTest {
    public static void main(String[] args) throws Throwable {
        for (int i = 0; i < 10; i++) {
            Object obj = System.currentTimeMillis() % 2 == 0 ? System.out : new ClassA();
            //无论obj最终是哪个实现类，下面这句都能正确调用到println方法
            getPrintlnMH(obj).invokeExact("icyfenix");
        }
    }

    private static MethodHandle getPrintlnMH(Object receiver) throws NoSuchMethodException, IllegalAccessException {
        //MethodType：代表“方法类型”，包含了方法得返回值（methodType()的第一个参数）和具体以参数（第二以及以后的参数）
        MethodType mt = MethodType.methodType(void.class, String.class);
        //lookup()方法来自于MethodHandles.lookup，这句的作用是在指定类中查找符合给定的方法名称、方法类型，并且符合调用权限的方法句柄
        return MethodHandles.lookup().findVirtual(receiver.getClass(), "println", mt).bindTo(receiver);
    }

    private static class ClassA {
        public void println(String s) {
            System.out.println("ClassA:" + s);
        }
    }
}
